namespace AgentJohnson.CodeAnnotations
{
  using System;
  using System.Xml;
  using JetBrains.Application;
  using JetBrains.Application.Components;
  using JetBrains.Application.Configuration;
  using Resharper.Abstractions.Settings;
  using Resharper.Abstractions.Shell;

  /// <summary>Defines the <see cref="CodeAnnotationSettings"/> class.</summary>
  [ShellComponent(ProgramConfigurations.VS_ADDIN)]
  public class CodeAnnotationSettings : SettingsBase, IDisposable
  {
    #region Constructors and Destructors

    /// <summary>Initializes a new instance of the <see cref="CodeAnnotationSettings"/> class.</summary>
    /// <param name="shellSettingsComponent">The shell settings component.</param>
    public CodeAnnotationSettings(ShellSettingsComponent shellSettingsComponent)
    {
      this.PublicAssertion = "Assert.ArgumentNotNull({0}, \"{0}\");";
      this.NonPublicAssertion = "Debug.ArgumentNotNull({0}, \"{0}\");";

      this.ShellSettingsComponent = shellSettingsComponent;
      shellSettingsComponent.LoadSettings(this, XmlExternalizationScope.WorkspaceSettings, "CodeAnnotations");
    }

    /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
    public void Dispose()
    {
      this.ShellSettingsComponent.SaveSettings(this, XmlExternalizationScope.WorkspaceSettings, "CodeAnnotations");
    }

    #endregion

    #region Properties

    /// <summary>
    /// Gets the instance.
    /// </summary>
    /// <value>The instance.</value>
    public static CodeAnnotationSettings Instance
    {
      get
      {
        return ShellManager.GetComponent<CodeAnnotationSettings>();
      }
    }

    /// <summary>
    /// Gets or sets a value indicating whether [non public assertion].
    /// </summary>
    /// <value><c>true</c> if [non public assertion]; otherwise, <c>false</c>.</value>
    [XmlExternalizable("")]
    public string NonPublicAssertion { get; set; }

    /// <summary>
    /// Gets or sets a value indicating whether [public assertion].
    /// </summary>
    /// <value><c>true</c> if [public assertion]; otherwise, <c>false</c>.</value>
    [XmlExternalizable("")]
    public string PublicAssertion { get; set; }

    #endregion

    #region Public Methods

    /// <summary>Reads the settings.</summary>
    /// <param name="doc">The document.</param>
    public void ReadSettings(XmlDocument doc)
    {
      var publicAssertionNode = doc.SelectSingleNode("/settings/valueanalysis/publicassertion");
      if (publicAssertionNode != null)
      {
        this.PublicAssertion = publicAssertionNode.InnerText;
      }

      var nonPublicAssertionNode = doc.SelectSingleNode("/settings/valueanalysis/nonpublicassertion");
      if (nonPublicAssertionNode != null)
      {
        this.NonPublicAssertion = nonPublicAssertionNode.InnerText;
      }
    }

    /// <summary>Writes the specified writer.</summary>
    /// <param name="writer">The writer.</param>
    public void WriteSettings(XmlTextWriter writer)
    {
      writer.WriteStartElement("valueanalysis");

      writer.WriteElementString("publicassertion", this.PublicAssertion);
      writer.WriteElementString("nonpublicassertion", this.NonPublicAssertion);

      writer.WriteEndElement();
    }

    #endregion

  }
}